<template>
  <view class="acme-action-sheet" @touchmove.stop.prevent
    :class="{'acme-action-sheet-card': mode === 'card'}"
  >
    <view class="overlay" @click="clickOverlay" :style="[showOverlay, { transitionDuration: `${duration}s` }]"></view>
    
    <view class="panel" :style="[panelStyle, showPopup, { transform, transition: duration + 's' }]">
      <view class="actions">
        <view class="item" v-for="(item, index) in actions" :key="index" @click="handleSelect(item, index)"
          :style="[itemStyle]"
        >
          <image :src="item.icon" v-if="item.icon"></image>
          <text :style="{color: item.disabled ? '#ccc' : '#333'}">{{item.name}}</text>
        </view>
      </view>
      <view :style="[lineStyle]" v-if="mode !== 'card'"></view>
      <view class="cancel" @click="handleCancel" :style="[cancelStyle]">
        取消
      </view>
      <view :style="[safeAreaStyle]"></view>
    </view>
  </view>
</template>

<script>
  export default {
    name: "ActionSheet",
    props: {
      value: {
        type: Boolean,
        default: false,
      },
      // 选项配置（必填）
      actions: Array,
      // 面板样式
      styles: Object,
      // null：普通模式 ｜ card：卡片模式 
      mode: {
        type: String,
        default: ''
      },
      // 动画时长，单位秒
      duration: {
        type: Number,
        default: 0.25,
      },
      // 元素高度
      itemHeight: {
        type: Number,
        default: 110
      },
      // 取消按钮上面的线条样式
      lineStyle: {
        type: Object,
        default: () => {
          return {
            width: '100%',
            height: '16rpx',
            background: '#F7F7F7'
          }
        }
      },
      // 取消按钮高度
      cancelHeight: {
        type: Number,
        default: 110
      },
      // 是否在点击遮罩层后关闭
      clickOverlayClose: {
        type: Boolean,
        default: true,
      },
      // 遮罩透明度
      overlayOpacity: {
        type: Number,
        default: 0.65
      },
      // 跳转到应用内的某个页面
      navigateTo: {
        type: String,
        default: ''
      },
    },
    computed: {
      panelHeight() {
        let lineHeight = parseFloat(this.lineStyle.height)
        return this.itemHeight * this.actions.length + this.cancelHeight + this.safeAreaBottom + lineHeight + 'rpx'
      },
      panelStyle() {
        let { mode, panelHeight, safeAreaBottom } = this
        return Object.assign(
          {
            height: panelHeight,
            background: "#fff",
            bottom: mode === 'card' ? `${safeAreaBottom || 20}rpx` : 0
          },
          this.styles
        );
      },
      itemStyle() {
        let { itemHeight } = this
        return {
          height: `${itemHeight}rpx`, 
          lineHeight: `${itemHeight}rpx`
        }
      },
      cancelStyle() {
        let { cancelHeight } = this
        return {
          height: `${cancelHeight}rpx`, 
          lineHeight: `${cancelHeight}rpx`
        }
      },
      safeAreaStyle() {
        return {
          width: '100%',
          height: `${this.safeAreaBottom}rpx`
        }
      }
    },
    watch: {
      value(show) {
        let { panelStyle } = this;
        let { height } = panelStyle;
        this.transform = `translateY(${height})`;

        if (show) {
          this.openPopup();
        } else {
          this.closePopup();
        }
      },
    },
    data() {
      return {
        showOverlay: {
          display: "none"
        },
        showPopup: {
          display: "none"
        },
        transform: "",
        safeAreaBottom: 0
      };
    },
    mounted() {
      this.getSystemInfo()
    },
    methods: {
      // 打开弹窗
      openPopup() {
        this.showPopup = {}
        this.showOverlay = {}

        setTimeout(() => {
          this.transform = `translateY(0)`
          this.showOverlay = { backgroundColor: `rgba(0, 0, 0, ${this.overlayOpacity})` }
          this.opened()
        }, 50)
      },
      // 关闭弹窗
      closePopup() {
        this.showOverlay = { backgroundColor: "rgba(0, 0, 0, 0)" }
        setTimeout(() => {
          this.$set(this.showPopup, "display", "none")
          this.showOverlay = { display: "none" }
        }, this.duration * 1000)
      },
      // 打开弹出层且动画结束后触发
      opened() {
        setTimeout(() => {
          this.$emit("opened")
        }, this.duration * 1000)
      },
      // 点击遮罩层时触发
      clickOverlay() {
        if (this.clickOverlayClose) {
          this.$emit("clickOverlay")
          this.$emit("input", false)
          this.close()
        }
      },
      handleCancel() {
        this.$emit("handleCancel")
        this.$emit("input", false)
        this.close()
      },
      // 关闭弹出层时触发
      close() {
        this.$emit("close")
        this.closed()
      },
      // 关闭弹出层且动画结束后触发
      closed() {
        setTimeout(() => {
          this.$emit("closed")
        }, this.duration * 1000)
      },
      handleSelect(item, index) {
        let { path, disabled, navigateTo, redirectTo, reLaunch, switchTab } = item
        if(disabled) { return }
        
        if(navigateTo) {
          uni.navigateTo({ url: navigateTo })
        }
        if(redirectTo) {
          uni.redirectTo({ url: redirectTo })
        }
        if(reLaunch) {
          uni.reLaunch({ url: reLaunch })
        }
        if(switchTab) {
          uni.switchTab({ url: switchTab })
        }
        this.$emit('select', {item, index})
        this.$emit("input", false)
        this.close()
      },
      getSystemInfo() {
        try {
          const res = uni.getSystemInfoSync()
          this.safeAreaBottom = res.safeAreaInsets.bottom
        } catch (e) {}
      },
    },
  }
</script>

<style lang="scss" scoped>
  @import './index.scss';
</style>